/*
* 插件: jSign
* 描述: JavaScript 签名服务接口
* 版本: 2.1.0
*
* */

/**
 * 签名脚本对象
 * 所属 [用户]
 * @returns {*}
 */

function jSign() {
    if (!!window.WebSocket && window.WebSocket.prototype.send) {
        this.net = createNet();
        return this;
    }
    else {
        return null;
    }
}

/**
 * 初始化签名对象
 * 所属 [用户]
 * @param callback = function(status)
 * @returns {*}
 */

jSign.prototype.Init = function (callback) {
    if (this.net == null) {
        callback(0);
        return null;
    }
    this.funcs = [];
    this.rets = [];
    this.rcb = callback;
    this.cid = 1;

    this.net.setStatusCallback(this, this.NetStatusCallback);
    this.net.setDataCallback(this, this.NetDataCallback);
    let port = location.protocol === "https:" ? "12268" : "12267";
    this.net.connect("127.0.0.1:" + port);
    return this;
};

/**
 * 对象销毁
 * 所属 [用户]
 * @param callback = function(status)
 */
jSign.prototype.Destroy = function (callback) {
    this.funcs = [];
    this.net.disconnect();
    this.net.setStatusCallback(null, null);
    this.net.setDataCallback(null, null);
    if (typeof callback === "function") {
        callback(true);
    }
};

/**
 * =====================================================================================
 * 公共用户接口--通用的签名接口
 *
 */

/**
 * 获取设备连接状态
 * @param callback = function(status,data)
 * if(status){
 *      data.model  //通过data.model获取当前设备型号
 * }
 * @constructor
 */
jSign.prototype.Status = function (callback) {
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.Status, {}, callback);
};

/**
 * 弹出签名对话框
 * @param callback = function(status)
 */
jSign.prototype.BeginSign = function (callback) {
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.BeginSign, {}, callback);
};

/**
 * 关闭签名对话框
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.EndSign = function (callback) {
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.EndSign, {}, callback);
};

/**
 * 清除画板
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.ClearSign = function (callback) {
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.ClearSign, {}, callback);
};

/**
 * 设置画笔线条宽度范围
 * 所属 [用户]
 * @param min = [1-24]，默认1
 * @param max = [1-24]，默认4
 * @param callback = function(status)
 */
jSign.prototype.SetPenSize = function (min, max, callback) {
    let args = {"min": min, "max": max};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.SetPenSize, args, callback);
};

/**
 * 设置笔颜色
 * @param r
 * @param g
 * @param b
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.SetPenColor = function (r, g, b, callback) {
    let args = {"r": r, "g": g, "b": b};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.SetPenColor, args, callback);
};

/**
 * 设置画板边框颜色，该边框不会体现在最终的笔迹图像中
 * @param r
 * @param g
 * @param b
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.SetBorderColor = function (r, g, b, callback) {
    let args = {"r": r, "g": g, "b": b};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.SetBorderColor, args, callback);
};

/**
 * 设置签字区域背景颜色，默认白色
 * @param r
 * @param g
 * @param b
 * @param callback = function(status)
 */
jSign.prototype.SetBKColor = function (r, g, b, callback) {
    let args = {"r": r, "g": g, "b": b};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.SetBKColor, args, callback);
};

/**
 * 保存笔迹图像到本地文件
 * @param path = 本地文件路径，例：D:\\sign.png
 * @param w = 指定宽度，默认0使用画板宽度
 * @param h = 指定高度，默认0使用画板高度
 * @param transparent =1 背景透明，=0 背景不透明
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.SaveSignToFile = function (path, w, h, transparent, callback) {
    let args = {"path": path, "w": w, "h": h, "transparent": transparent};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.SaveSignToFile, args, callback);
};

/**
 * 获取笔迹图像Base64字符串
 * @param w = 指定宽度，默认0使用画板宽度
 * @param h = 指定高度，默认0使用画板高度
 * @param transparent =1 背景透明，=0 背景不透明
 * @param callback = function(status,data)
 * if(status){
 *     data.img //通过data.img成员获取图像base64,不包含图像前缀
 * }
 * @constructor
 */
jSign.prototype.GetSignBase64 = function (w, h, transparent, callback) {
    let args = {"w": w, "h": h, "transparent": transparent};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.GetSignBase64, args, callback);
};

/**
 * 是否能使用笔来控制系统鼠标
 * @param enable
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.ActivateMouse = function (enable, callback) {
    let args = {"enable": enable};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.ActivateMouse, args, callback);
};

/**
 * 将签名窗口移动指定的屏幕位置
 * @param x 当设备为签批屏时，以签批屏左部开始计算，否则以主屏幕左部开始计算
 * @param y 当设备为签批屏时，以签批屏顶部开始计算，否则以主屏幕顶部开始计算
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.MoveSignWindow = function (x, y, callback) {
    let args = {"x": x, "y": y};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.MoveSignWindow, args, callback);
};

/**
 * 重新设置签名区域大小
 * @param w = 指定新的书写区域宽度
 * @param h = 指定新的书写区域高度
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.ResizeSignView = function (w, h, callback) {
    let args = {"w": w, "h": h};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.ResizeSignView, args, callback);
};

/**
 * 设置签名窗口标题文本
 * @param title = 窗口标题文本
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.SetSignWindowText = function (title, callback) {
    let args = {"title": title};
    this.Emit(SS_MSG_TYPE.Sign, SS_IIDS.SetSignWindowText, args, callback);
};

/**
 * =====================================================================================
 * 公共用户接口--PDF文档签名接口
 *
 */

/**
 * 开始PDF文档签名
 * @param pdf = dataURL(pdf文档的Base64数据)
 * @param tags = 要签名的标签参数数组，支持多个标签，例：
 * [{"page":1,"x":0,"y":0,"w":240,"h":150,"type":1},
 * {"page":2,"x":0,"y":0,"w":240,"h":150,"type":2},
 * {"page":3,"x":0,"y":0,"w":240,"h":150,"type":3}]
 * type=1(手写签名)  type=2(指纹) type=3(签名&指纹)
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.PdfBeginSign = function (pdf, tags, callback) {
    let args = {"pdf": pdf, "tags": tags};
    this.Emit(SS_MSG_TYPE.Pdf, SS_IIDS.PdfBeginSign, args, callback, 5000);
};

/**
 * 仅预览不需要签名操作，该接口依赖PdfBeginSign
 * @param pdf = dataURL(pdf文档的Base64数据)
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.PdfPreview = function (pdf, callback) {
    let args = {"pdf": pdf, "tags": null};
    this.Emit(SS_MSG_TYPE.Pdf, SS_IIDS.PdfBeginSign, args, callback, 5000);
};

/**
 * 从URL打开pdf文档
 * @param url = pdf文档链接
 * @param tags = 要签名的标签参数数组，同PdfBeginSign的tags参数含义相同
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.PdfBeginSignFromURL = function (url, tags, callback) {
    let args = {"url": url, "tags": tags};
    this.Emit(SS_MSG_TYPE.Pdf, SS_IIDS.PdfBeginSignFromURL, args, callback);
};

/**
 * 结束PDF文件签名
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.PdfEndSign = function (callback) {
    this.Emit(SS_MSG_TYPE.Pdf, SS_IIDS.PdfEndSign, {}, callback);
};

/**
 * 当前打开的PDF文档跳转到指定页面
 * @param page = 要跳转的页面编号，以1开始计数
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.PdfGotoPage = function (page, callback) {
    let args = {"page": page};
    this.Emit(SS_MSG_TYPE.Pdf, SS_IIDS.PdfGotoPage, args, callback);
};

/**
 * 向当前打开的PDF插入图像
 * @param page = 指定PDF页面编号，以1开始计数
 * @param x = 指定图像位于页面x坐标
 * @param y = 指定图像位于页面y坐标
 * @param w = 指定图像位于页面的显示宽度，当图像实际大小与w不一致时，图像宽将会缩放至w
 * @param h = 指定图像位于页面的显示高度，当图像实际大小与w不一致时，图像高将会缩放至h
 * @param img = 图片base64（不包含图像前缀）
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.PdfWriteImage = function (page, x, y, w, h, img, callback) {
    let args = {"page": page, "x": x, "y": y, "w": w, "h": h, "img": img};
    this.Emit(SS_MSG_TYPE.Pdf, SS_IIDS.PdfWriteImage, args, callback);
};

/**
 * 设置PDF签名操作模式
 * @param mode = 0(顺序模式)  mode = 1(可选模式)
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.PdfSetOperationMode = function (mode, callback) {
    let args = {"mode": mode};
    this.Emit(SS_MSG_TYPE.Pdf, SS_IIDS.PdfSetOperationMode, args, callback);
};


/**
 * =====================================================================================
 * 公共用户接口--指纹采集接口
 *
 */
/**
 * 启动指纹采集程序
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.FingerBeginCapture = function (callback) {
    this.Emit(SS_MSG_TYPE.Finger, SS_IIDS.FingerBeginCapture, {}, callback);
};

/**
 * 关闭指纹采集程序
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.FingerEndCapture = function (callback) {
    this.Emit(SS_MSG_TYPE.Finger, SS_IIDS.FingerEndCapture, {}, callback);
};

/**
 * 获取采集的指纹图像
 * @param callback = function(status,data)
 *if(status){
 *     data.img //通过data.img成员获取指纹图像base64,不包含图像前缀
 * }
 * @constructor
 */
jSign.prototype.FingerCaptureImage = function (callback) {
    this.Emit(SS_MSG_TYPE.Finger, SS_IIDS.FingerCaptureImage, {}, callback);
};


/**
 * =====================================================================================
 * 公共用户接口--身份证采集接口
 *
 */
/**
 * 启动身份证采集程序
 * @param callback = function(status)
 * @constructor
 */
//接口保留
// jSign.prototype.IDCardBeginCapture = function (callback) {
//     this.Emit(SS_MSG_TYPE.IDCard, SS_IIDS.IDCardBeginCapture, {}, callback);
// };
/**
 * 关闭身份证采集程序
 * @param callback = function(status)
 * @constructor
 */
//接口保留
// jSign.prototype.IDCardEndCapture = function (callback) {
//     this.Emit(SS_MSG_TYPE.IDCard, SS_IIDS.IDCardEndCapture, {}, callback);
// };
/**
 * 获取身份证信息
 * @param callback = function(status,data)
 *
 * @constructor
 */
jSign.prototype.IDCardGetInfo = function (callback) {
    this.Emit(SS_MSG_TYPE.IDCard, SS_IIDS.IDCardGetInfo, {}, callback);
};
/**
 * =====================================================================================
 * 公共用户接口--摄像头接口
 *
 */

/**
 * 打开摄像头
 * @param direction
 * direction = 0(前置摄像头) direction = 1(后置摄像头)
 * 前置摄像头通常对应高拍仪镜头
 * 后置摄像头通常对应人脸拍摄镜头
 * @param position position = 0(主屏) position = 1(签批屏)
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.CameraBeginCapture = function (direction, position, callback) {
    let args = {"direction": (direction !== 0 ? 1 : 0), "position": (position !== 0 ? 1 : 0)};
    this.Emit(SS_MSG_TYPE.Camera, SS_IIDS.CameraBeginCapture, args, callback, 5000);
};

/**
 * 关闭摄像头
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.CameraEndCapture = function (callback) {
    this.Emit(SS_MSG_TYPE.Camera, SS_IIDS.CameraEndCapture, {}, callback);
};

/**
 * 捕获图像
 * @param callback = function(status,data)
 *if(status){
 *     data.img //通过data.img成员获取拍照图像base64,不包含图像前缀
 * }
 * @constructor
 */
jSign.prototype.CameraCaptureImage = function (callback) {
    this.Emit(SS_MSG_TYPE.Camera, SS_IIDS.CameraCaptureImage, {}, callback);
};

/**
 * 开始视频录制，在使用该接口之前需先打开摄像头
 * @param duration = 录制时间，最长不超过1800秒
 * @param localPath = 本地存储路径（例："E:\video\20220101_xxx.avi"）
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.CameraStartVideo = function (duration, localPath, callback) {
    this.Emit(SS_MSG_TYPE.Camera, SS_IIDS.CameraStartVideo, {"duration": duration, "path": localPath}, callback);
};

/**
 * 停止视频录制
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.CameraStopVideo = function (callback) {
    this.Emit(SS_MSG_TYPE.Camera, SS_IIDS.CameraStopVideo, {}, callback);
};

/**
 * 获取本次视频录制的文件信息，该接口需在录制停止状态或手动停止视频录制的条件下使用
 * @param callback = function(status,data)
 * if(status)
 * {
 *     data.path        //调用者指定的文件全路径
 *     data.file        //文件名称
 *     data.size        //文件大小，单位：字节
 *     data.duration    //视频实际时长，单位：秒
 * }
 * @constructor
 */
jSign.prototype.CameraGetVideoInfo = function (callback) {
    this.Emit(SS_MSG_TYPE.Camera, SS_IIDS.CameraGetVideoInfo, {}, callback);
};
/**
 * =====================================================================================
 * 公共用户接口--人证核验接口
 *
 */
/**
 * 启动人证核验程序
 * @param threshold = 人脸与证件照匹配通过阈值，该值取值范围60-99，默认值80
 * threshold值越大匹配越精准，失败率同时也会提高
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.IDFaceBeginVerify = function (threshold, callback) {
    let param = {"threshold": threshold};
    this.Emit(SS_MSG_TYPE.IDFace, SS_IIDS.IDFaceBeginVerify, param, callback);
};

/**
 * 结束人证核验程序
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.IDFaceEndVerify = function (callback) {
    this.Emit(SS_MSG_TYPE.IDFace, SS_IIDS.IDFaceEndVerify, {}, callback);
};

/**
 * =====================================================================================
 * 公共用户接口--通用接口
 */

/**
 * 打开服务评价窗口
 * @param name = 人员名称
 * @param id = 人员编号
 * @param position = 职位
 * @param photo = 照片base64
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.CommonBeginEvaluate = function (name, id, position, photo, callback) {
    let param = {"name": name, "id": id, "position": position, "photo": photo};
    this.Emit(SS_MSG_TYPE.Common, SS_IIDS.CommonBeginEvaluate, param, callback);
};

/**
 * 结束服务评价
 * @param callback = function(status)
 * @constructor
 */
jSign.prototype.CommonEndEvaluate = function (callback) {
    this.Emit(SS_MSG_TYPE.Common, SS_IIDS.CommonEndEvaluate, {}, callback);
};


/**
 * =====================================================================================
 * 由用户实现的事件接口，可选
 */

/**
 * 网络状态通知,物理设备状态改变事件(接入/移除) 函数，格式 function(e)
 * 网络断开事件 e = {"type":"net","status":0}     1=连接  0=断开
 * 设备插拔事件 e = {"type":"device","status":0}  1=连接  0=断开
 * 所属 [用户]
 * @type {null}
 */
jSign.prototype.onStatusChanged = null;


/**
 * 签名窗口的“取消”按钮点击事件
 * 所属 [用户]
 * @type {null}
 */
jSign.prototype.onSignCancel = null;

/**
 * 签名窗口的“清除”按钮点击事件
 * 所属 [用户]
 * @type {null}
 */
jSign.prototype.onSignClear = null;

/**
 *签名窗口的“确认”按钮点击事件
 * 所属 [用户]
 * @type {null}
 */
jSign.prototype.onSignConfirm = null;


jSign.prototype.onFingerCancel = null;
jSign.prototype.onFingerRescan = null;
jSign.prototype.onFingerConfirm = null;

jSign.prototype.onPdfCancel = null;
jSign.prototype.onPdfConfirm = null;
jSign.prototype.onPdfError = null;

jSign.prototype.onCameraCancel = null;
jSign.prototype.onCameraCaptured = null;
jSign.prototype.onCameraConfirm = null;
jSign.prototype.onCameraVideoFinished = null;

jSign.prototype.onIDFaceVerify = null;

jSign.prototype.onEvaluationCancel = null;
jSign.prototype.onEvaluationConfirm = null;

/**
 * =====================================================================================
 * 以下为插件私有对象
 */

/**
 请求消息类型
 */
var SS_MSG_TYPE = {
    Sign: 1,
    Pdf: 2,
    Finger: 3,
    Camera: 4,
    IDCard: 5,
    IDFace: 6,
    Common: 7
};

/**
 * 用户事件类型
 * @type {{}}
 */
var SS_ETYPE = {
    Click: "click",
    Key: "key",
    Custom: "custom"
};

/**
 * 事件ID定义
 */
var SS_EIDS = {
    SignCancel: 1,
    SignClear: 2,
    SignConfirm: 3,

    PdfCancel: 11,
    PdfConfirm: 16,

    FingerCancel: 21,
    FingerRescan: 22,
    FingerConfirm: 23,

    CameraCancel: 31,
    CameraCaptured: 32,
    CameraConfirm: 33,

    EvaluationCancel: 41,
    EvaluationConfirm: 42,

    IDFaceVerify: 51,
    CameraVideoFinished: 52,
    PdfError: 61,

    Status: 100
};

/**
 * 接口ID定义
 *
 */
var SS_IIDS = {
    Status: 1001,
    BeginSign: 1002,
    EndSign: 1003,
    ClearSign: 1004,
    SetPenSize: 1005,
    SetPenColor: 1006,
    SetBorderColor: 1007,
    SetBKColor: 1008,
    SaveSignToFile: 1009,
    GetSignBase64: 1010,
    ActivateMouse: 1011,
    MoveSignWindow: 1012,
    ResizeSignView: 1013,
    SetSignWindowText: 1014,

    ShowWebPage: 1051,
    CloseWebPage: 1052,

    PdfBeginSign: 1101,
    PdfEndSign: 1102,
    PdfGotoPage: 1103,
    PdfWriteImage: 1104,
    PdfBeginSignFromURL: 1105,
    PdfSetOperationMode: 1106,

    FingerBeginCapture: 1201,
    FingerEndCapture: 1202,
    FingerCaptureImage: 1203,

    CameraBeginCapture: 1301,
    CameraEndCapture: 1302,
    CameraCaptureImage: 1303,
    CameraStartVideo: 1311,
    CameraStopVideo: 1312,
    CameraGetVideoInfo: 1313,


    IDCardBeginCapture: 1401,
    IDCardEndCapture: 1402,
    IDCardGetInfo: 1403,

    IDFaceBeginVerify: 1501,
    IDFaceEndVerify: 1502,

    CommonBeginEvaluate: 1601,
    CommonEndEvaluate: 1602
};

/**
 * 网络状态改变响应函数
 * 所属 [私有]
 * @param mgr
 * @param status
 */
jSign.prototype.NetStatusCallback = function (mgr, status) {
    if (!!mgr.onStatusChanged) {
        mgr.onStatusChanged({"type": "net", "status": status});
    }
    if (!!mgr.rcb) {
        mgr.rcb(status);
        mgr.rcb = null;
    }
};

/**
 * 网络数据响应回调函数
 * 所属 [私有]
 * @param mgr
 * @param data
 */
jSign.prototype.NetDataCallback = function (mgr, data) {
    let packet = JSON.parse(data);
    if (packet.hasOwnProperty("status") && packet.hasOwnProperty("data")) {
        /*函数执行的返回*/
        let status = packet.status === 1;
        let cid = packet.cid;
        let type = packet.type;
        let iid = packet.iid;
        let data = packet.data;

        if (mgr.funcs.hasOwnProperty(iid)) {
            if (Object.getOwnPropertyNames(data).length > 0)
                mgr.funcs[iid](status, data);
            else
                mgr.funcs[iid](status);
        }

        mgr.funcs[iid] = null;

        if (mgr.rets.hasOwnProperty(cid)) {
            clearTimeout(mgr.rets[cid].timer);
            mgr.rets[cid] = null;
        }

    } else if (packet.hasOwnProperty("event") && packet.hasOwnProperty("data")) {
        /*事件响应*/
        let data = packet.data;
        let eid = packet.id;
        switch (packet.event) {
            case  SS_ETYPE.Click: {
                switch (eid) {
                    case SS_EIDS.SignCancel: {
                        if (!!mgr.onSignCancel && (typeof mgr.onSignCancel) === "function") {
                            mgr.onSignCancel();
                        }
                    }
                        break;
                    case SS_EIDS.SignClear: {
                        if (!!mgr.onSignClear && (typeof mgr.onSignClear) === "function") {
                            mgr.onSignClear();
                        }
                    }
                        break;
                    case SS_EIDS.SignConfirm: {
                        if (!!mgr.onSignConfirm && (typeof mgr.onSignConfirm) === "function") {
                            mgr.onSignConfirm(data);
                        }
                    }
                        break;
                    case SS_EIDS.PdfCancel: {
                        if (!!mgr.onPdfCancel && (typeof mgr.onPdfCancel) === "function") {
                            mgr.onPdfCancel(data);
                        }
                    }
                        break;
                    case SS_EIDS.PdfConfirm: {
                        if (!!mgr.onPdfConfirm && (typeof mgr.onPdfConfirm) === "function") {
                            mgr.onPdfConfirm(data);
                        }
                    }
                        break;

                    case SS_EIDS.FingerCancel: {
                        if (!!mgr.onFingerCancel && (typeof mgr.onFingerCancel) === "function") {
                            mgr.onFingerCancel(data);
                        }
                    }
                        break;
                    case SS_EIDS.FingerRescan: {
                        if (!!mgr.onFingerRescan && (typeof mgr.onFingerRescan) === "function") {
                            mgr.onFingerRescan(data);
                        }
                    }
                        break;
                    case SS_EIDS.FingerConfirm: {
                        if (!!mgr.onFingerConfirm && (typeof mgr.onFingerConfirm) === "function") {
                            mgr.onFingerConfirm(data);
                        }
                    }
                        break;
                    case SS_EIDS.CameraCancel: {
                        if (!!mgr.onCameraCancel && (typeof mgr.onCameraCancel) === "function") {
                            mgr.onCameraCancel(data);
                        }
                    }
                        break;
                    case SS_EIDS.CameraCaptured: {
                    }
                        break;
                    case SS_EIDS.CameraConfirm: {
                        if (!!mgr.onCameraConfirm && (typeof mgr.onCameraConfirm) === "function") {
                            mgr.onCameraConfirm(data);
                        }
                    }
                        break;
                    case SS_EIDS.EvaluationCancel: {
                        if (!!mgr.onEvaluationCancel && (typeof mgr.onEvaluationCancel) === "function") {
                            mgr.onEvaluationCancel(data);
                        }
                    }
                        break;
                    case SS_EIDS.EvaluationConfirm: {
                        if (!!mgr.onEvaluationConfirm && (typeof mgr.onEvaluationConfirm) === "function") {
                            mgr.onEvaluationConfirm(data);
                        }
                    }
                        break;
                }
            }
                break;
            case SS_ETYPE.Key: {

            }
                break;
            case  SS_ETYPE.Custom: {
                switch (eid) {
                    case SS_EIDS.Status: {
                        if (!!mgr.onStatusChanged && (typeof mgr.onStatusChanged) === "function") {
                            mgr.onStatusChanged(data);
                        }
                    }
                        break;
                    case SS_EIDS.IDFaceVerify: {
                        if (!!mgr.onIDFaceVerify && (typeof mgr.onIDFaceVerify) === "function") {
                            mgr.onIDFaceVerify(data);
                        }
                    }
                        break;
                    case SS_EIDS.CameraVideoFinished: {
                        if (!!mgr.onCameraVideoFinished && (typeof mgr.onCameraVideoFinished) === "function") {
                            mgr.onCameraVideoFinished(data);
                        }
                    }
                        break;
                    case SS_EIDS.PdfError: {
                        if (!!mgr.onPdfError && (typeof mgr.onPdfError) === "function") {
                            mgr.onPdfError(data);
                        }
                    }
                        break;
                }
            }
                break;
        }
    }
    console.log(packet);
};

/**
 * 接口请求超时处理回调函数
 * 所属 [私有]
 * @param sender
 * @param cid
 */
jSign.prototype.emitTimeout = function (sender, cid) {
    if (!!sender) {
        if (sender.rets.hasOwnProperty(cid.toString())) {
            let callback = sender.rets[cid.toString()].func;
            if (!!callback) {
                callback(false, ["function request timeout"]);
            }
        }
    }
};

/**
 * 接口调用请求
 * 所属 [私有]
 *
 * @param type  请求类型
 * @param iid   接口id
 * @param args  附加参数
 * @param callback  回调函数
 * @constructor
 */
jSign.prototype.Emit = function (type, iid, args, callback, timeout) {

    if (!this.hasOwnProperty("funcs")) {
        callback(false, "jSign object uninitialized");
        return;
    }

    if (typeof callback === "function") {
        this.funcs[iid] = callback;
    }
    if (this.cid > 1024) {
        this.cid = 1;
    }
    let cid = ++this.cid;

    let msg = {"cid": cid, "type": type, "iid": iid, "args": args};

    this.net.write(JSON.stringify(msg));

    let t = arguments[4] ? arguments[4] : 2000;

    this.rets[cid.toString()] = {
        func: callback,
        timer: setTimeout(this.emitTimeout, t, this, cid)
    };
};

/**
 * 创建一个网络对象
 * 所属 [私有]
 * @returns {{ws: null, url: null, data: {mgr: null, callback: null}, status: {mgr: null, callback: null}, reconn_timer: null, timeout: number, connect: connect, disconnect: disconnect, reconnect: reconnect, do_reconnect: do_reconnect, getNetStatus: getNetStatus, setDataCallback: setDataCallback, setStatusCallback: setStatusCallback, write: write}}
 */
function createNet() {
    return {
        ws: null,
        url: null,
        data: {mgr: null, callback: null},
        status: {mgr: null, callback: null},
        reconn_timer: null,
        timeout: 2000,
        connect: function (url) {
            this.url = url;
            url = (location.protocol === "https:" ? "wss://" : "ws://") + url;
            this.ws = new WebSocket(url);
            this.ws.owner = this;
            this.ws.onopen = function () {
                let owner = this.owner;
                if (!!owner.status.callback) {
                    owner.status.callback(owner.status.mgr, true);
                }
            };
            this.ws.onclose = function (e) {
                let owner = this.owner;
                if (!!owner.status.callback) {
                    owner.status.callback(owner.status.mgr, false);
                }
            };
            this.ws.onmessage = function (e) {
                let owner = this.owner;
                if (!!owner.data.callback) {
                    owner.data.callback(owner.data.mgr, e.data);
                }
            };
            this.ws.onerror = function (e) {
                let owner = this.owner;
                owner.disconnect();
            }
        },
        disconnect: function () {
            if (this.ws != null) {
                this.ws.close();
                this.ws = null;
            }
        },
        reconnect: function () {
            this.disconnect();
            this.connect(this.url);

        },
        do_reconnect: function (activate) {
            if (activate !== true && reconn_timer != null) {
                clearInterval(this.reconn_timer);
                this.reconn_timer = null;
            }
            if (activate === true && reconn_timer == null) {
                this.reconn_timer = setInterval(function (net) {
                    console.log("net reconnect");
                }, this.timeout);
            }
        },
        getNetStatus: function () {
            if (!!this.ws) {
                return this.ws.readyState === WebSocket.OPEN;
            }
            return false;
        },
        setDataCallback: function (mgr, callback) {
            this.data.mgr = mgr;
            this.data.callback = callback;
        },
        setStatusCallback: function (mgr, callback) {
            this.status.mgr = mgr;
            this.status.callback = callback;
        },
        write: function (data) {
            if (this.getNetStatus()) {
                try {
                    this.ws.send(data);
                }
                catch (e) {
                    return false;
                }
                return true;
            }
            return false;
        }
    }
}
